#include <fstream>
#include <boost/filesystem.hpp>

#include "BackupFilesReceiver.h"
#include "FileSegmentHeader.h"

#define RECV_BUFFER_SIZE 512


namespace ip = boost::asio::ip;
namespace fs = boost::filesystem;


BackupFilesReceiver::BackupFilesReceiver(const LogWriter& logWriter,
	unsigned short commPort) :
	m_logWriter(logWriter),
	m_socket(m_ioService, ip::udp::endpoint(ip::udp::v4(), commPort))
{}


void BackupFilesReceiver::set_storage_directory(
	const std::string& storageDirPathStr)
{
	m_storageDirPath = storageDirPathStr;
}


void BackupFilesReceiver::run()
{
	{
		std::stringstream ss;
		ss << "Listening on port " << m_socket.local_endpoint().port() << ".";
		m_logWriter.write_info(ss.str());
	}

	/* Rester dans l'attente de messages indefiniment. */
	while (true)
	{
		ip::udp::endpoint senderEndpoint;
		std::array<char, RECV_BUFFER_SIZE> buffer;
		size_t msgSize = 0;

		/* Attendre la reception d'un fragment de fichier. */
		msgSize = m_socket.receive_from(
			boost::asio::buffer(buffer), senderEndpoint);

		/* S'occuper du fragment recu. */
		handle_reception(buffer.data(), msgSize);
	}
}


void BackupFilesReceiver::handle_reception(const char* buffer, std::size_t msgSize)
{
	FileSegmentHeader filePartHeader;
	fs::path segmentFilePath;
	std::ofstream fileSegment;
	
	/* Extraire les informations de l'en-tete. */
	filePartHeader.read_from(buffer, msgSize);
	buffer += filePartHeader.size();

	/* Construire le chemin du fichier dans lequel sauver le segment. */
	{
		std::stringstream segmentFileName;
		segmentFileName << filePartHeader.fileName << "_" << filePartHeader.segmentNum;
		(segmentFilePath = m_storageDirPath) /= segmentFileName.str();
	}

	fileSegment.open(segmentFilePath.native(), std::ios_base::trunc);

	/* Ecrire effectivement le segment dans le fichier cree. */
	fileSegment.write(buffer, msgSize-filePartHeader.size());
	fileSegment.flush();

	fileSegment.close();
}
